/*
 * PhotonRTOS础光实时操作系统 -- mpu
 *
 * Copyright (C) 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Jiayuan Liang <liangjiayuan@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef __ASM_MPU_H
#define __ASM_MPU_H

#include "Ifx_Types.h"
#include "IfxPort.h"
#include "IfxCpu_reg.h"
#include <asm/sections.h>

/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define DPR_GRANULARITY                 8                           /* Data Protection Range granularity in bytes   */
#define CPR_GRANULARITY                 32                          /* Code Protection Range granularity in bytes   */

/* Data Protection Ranges */
#define DATA_PROTECTION_RANGE_0         0
#define DATA_PROTECTION_RANGE_1         1
#define DATA_PROTECTION_RANGE_2         2
#define DATA_PROTECTION_RANGE_3         3
#define DATA_PROTECTION_RANGE_4         4
#define DATA_PROTECTION_RANGE_5         5
#define DATA_PROTECTION_RANGE_6         6
#define DATA_PROTECTION_RANGE_7         7
#define DATA_PROTECTION_RANGE_8         8
#define DATA_PROTECTION_RANGE_9         9
#define DATA_PROTECTION_RANGE_10        10
#define DATA_PROTECTION_RANGE_11        11
#define DATA_PROTECTION_RANGE_12        12
#define DATA_PROTECTION_RANGE_13        13
#define DATA_PROTECTION_RANGE_14        14
#define DATA_PROTECTION_RANGE_15        15
#define DATA_PROTECTION_RANGE_16        16
#define DATA_PROTECTION_RANGE_17        17

/* Code Protection Ranges */
#define CODE_PROTECTION_RANGE_0         0
#define CODE_PROTECTION_RANGE_1         1
#define CODE_PROTECTION_RANGE_2         2
#define CODE_PROTECTION_RANGE_3         3
#define CODE_PROTECTION_RANGE_4         4
#define CODE_PROTECTION_RANGE_5         5
#define CODE_PROTECTION_RANGE_6         6
#define CODE_PROTECTION_RANGE_7         7
#define CODE_PROTECTION_RANGE_8         8
#define CODE_PROTECTION_RANGE_9         9

/* Protection Sets */
#define PROTECTION_SET_0                0
#define PROTECTION_SET_1                1
#define PROTECTION_SET_2                2
#define PROTECTION_SET_3                3
#define PROTECTION_SET_4                4
#define PROTECTION_SET_5                5

/* LEDs */
#define LED_FIRST_HALF                  &MODULE_P13,0
#define LED_SECOND_HALF                 &MODULE_P13,1

/*********************************************************************************************************************/
/*------------------------------------------------Function Prototypes------------------------------------------------*/
/*********************************************************************************************************************/
/* MPU control functions */
void enable_memory_protection(void);
void define_data_protection_range(uint32 lowerBoundAddress, uint32 upperBoundAddress, uint8 range);
void define_code_protection_range(uint32 lowerBoundAddress, uint32 upperBoundAddress, uint8 range);
void enable_data_read(uint8 protectionSet, uint8 range);
void enable_data_write(uint8 protectionSet, uint8 range);
void enable_code_execution(uint8 protectionSet, uint8 range);

/*********************************************************************************************************************/
/*---------------------------------------------Function Implementations----------------------------------------------*/
/*********************************************************************************************************************/
/* Function to set the given Protection Set as active.
 * This function needs to be declared as inline because the Program Status Word (PSW) is one of the registers
 * automatically saved to the Context Save Area (CSA) when a function is called.
 * If this function was not declared as inline, the Upper Context (16 registers including the PSW) would be
 * automatically saved to the CSA and re-loaded when the function return, thus losing the change in the PSW.
 */
static inline void set_active_protection_set(uint8 protectionSet)
{
    Ifx_CPU_PSW PSWRegisterValue;
    PSWRegisterValue.U = __mfcr(CPU_PSW);               /* Get the Program Status Word (PSW) register value         */
    PSWRegisterValue.B.PRS = protectionSet;             /* Set the PRS bitfield to enable the Protection Set        */
    __mtcr(CPU_PSW, PSWRegisterValue.U);                /* Set the Program Status Word (PSW) register               */
}

#endif /* __ASM_MPU_H */
